package com.tonggedata.dataapi.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.tonggedata.dataapi.entity.ApiConfig;
import com.tonggedata.dataapi.mapper.ApiConfigMapper;
import com.tonggedata.dataapi.service.ApiConfigService;
import io.swagger.annotations.Api;
import org.apache.dolphinscheduler.api.utils.PageInfo;

import org.springframework.stereotype.Service;
import cn.hutool.core.bean.BeanUtil;

import com.tonggedata.dataapi.entity.ApiGroup;
import com.tonggedata.dataapi.service.ApiGroupService;
import com.tonggedata.dataapi.mapper.ApiGroupMapper;
import com.tonggedata.dataapi.dto.ApiGroupDto;
import com.tonggedata.dataapi.dto.ApiGroupParamDto;
import com.tonggedata.dataapi.util.ApiServiceUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.dao.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;

import java.util.*;

/**
 * ==================================================
 *
 * @author : tonggedata
 * @fileName:
 * @create : 2022-06-19 13:08:46
 * @Description： api业务分组表
 * ==================================================
 * @since 1.0.0
 */
@Service
public class ApiGroupServiceImpl extends ServiceImpl<ApiGroupMapper, ApiGroup> implements ApiGroupService {


    private static final Logger logger = LoggerFactory.getLogger(ApiGroupServiceImpl.class);

    @Autowired
    private ApiGroupMapper apiGroupMapper;

    @Autowired
    private ApiConfigMapper apiConfigMapper;

    public Result insert(User loginUser, ApiGroup apiGroup){
        Result<Object> result = new Result<>();
        apiGroupMapper.insert(apiGroup);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);
        return result;
    }

    @Override
    public Map<String, Object> queryApiGroup(long id) {
        Map<String, Object> result = new HashMap<>();
        ApiGroup apiGroup = getById(id);
        if (apiGroup == null) {
//            putMsg(result, Status.RESOURCE_NOT_EXIST);
            return result;
        }
        // type
        ApiGroupDto apiGroupDto = new ApiGroupDto();
        BeanUtil.copyProperties(apiGroup, apiGroupDto);

        result.put(Constants.DATA_LIST, apiGroupDto);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);
        return result;
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Result<Object> delete(User loginUser, long id) {
        Result<Object> result = new Result<>();
        try {
            ApiGroup apiGroup = getById(id);
            if (apiGroup == null) {
                logger.error("resource id {} not exist" , id);
                ApiServiceUtil.putMsg(result, Status.RESOURCE_NOT_EXIST);
                return result;
            }
            if (!ApiServiceUtil.hasPerm(loginUser, apiGroup.getCreateUser())) {
                ApiServiceUtil.putMsg(result, Status.USER_NO_OPERATION_PERM);
                return result;
            }
            apiGroup.setDeleted(1);
            apiGroup.setUpdateTime(new Date());
            apiGroup.setUpdateUser(loginUser.getUserName());

            apiGroupMapper.updateById(apiGroup);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (Exception e) {
            logger.error("delete apiGroup error" , e);
            throw new RuntimeException("delete apiGroup error" );
        }
        return result;
    }

    @Override
    public Result queryApiGroupListPaging(User loginUser, String searchVal, Integer pageNo, Integer pageSize) {
        Result result = new Result();
        Page<ApiGroup> apiGroupPage = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<ApiGroup> lambdaQuery = new LambdaQueryWrapper<ApiGroup>();
        if (!ApiServiceUtil.isAdmin(loginUser)) {
            lambdaQuery.eq(ApiGroup::getCreateUser, loginUser.getUserName());
        }
        if (StrUtil.isNotEmpty(searchVal)) {
            //lambdaQuery.eq(ApiGroup::getName, searchVal);
        }
        IPage<ApiGroup> ipage = page(apiGroupPage, lambdaQuery);
        //转换格式
        PageInfo<ApiGroup> pageInfo = new PageInfo<>(pageNo, pageSize);
        pageInfo.setTotal((int) ipage.getTotal());
        pageInfo.setTotalList(ipage.getRecords());
        result.setData(pageInfo);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);
        return result;
    }

    @Override
    public Map<String, Object> queryApiGroupList(User loginUser, String name) {
        Map<String, Object> result = new HashMap<>();

        LambdaQueryWrapper<ApiGroup> lambdaQuery = new LambdaQueryWrapper<ApiGroup>();
        String sqlSelect = lambdaQuery.getSqlSelect();
        System.out.println(sqlSelect);

        if (!ApiServiceUtil.isAdmin(loginUser)) {
            lambdaQuery.eq(ApiGroup::getCreateUser, loginUser.getUserName());
        }

        if (StrUtil.isNotEmpty(name)) {
            lambdaQuery.like(ApiGroup::getName, name);
        }

        List<ApiGroup> apiGroupList = apiGroupMapper.selectList(lambdaQuery);

        result.put(Constants.DATA_LIST, apiGroupList);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);

        return result;
    }


    @Override
    public Map<String, Object> queryApiGroupAndApiConfigList(User loginUser,String groupName, String apiName) {
        Map<String, Object> result = new HashMap<>();

        LambdaQueryWrapper<ApiConfig> apiConfigQuery = new LambdaQueryWrapper<ApiConfig>();
        LambdaQueryWrapper<ApiGroup> apiGroupQuery = new LambdaQueryWrapper<ApiGroup>();

        if (!ApiServiceUtil.isAdmin(loginUser)) {
            apiConfigQuery.eq(ApiConfig::getCreateUser, loginUser.getUserName());
            apiGroupQuery.eq(ApiGroup::getCreateUser, loginUser.getUserName());
        }

        if (StrUtil.isNotEmpty(apiName)) {
            apiConfigQuery.like(ApiConfig::getName, apiName);
        }

        if (StrUtil.isNotEmpty(groupName)) {
            apiGroupQuery.like(ApiGroup::getName, apiName);
            apiGroupQuery.eq(ApiGroup::getDeleted,0);
        }

        List<ApiGroup> apiGroupList = apiGroupMapper.selectList(apiGroupQuery);
        List<ApiConfig> apiConfigList = apiConfigMapper.selectList(apiConfigQuery);

        Map<Long,List<ApiConfig>> groupMap = new HashMap<>();

        for (ApiConfig apiConfig : apiConfigList) {
            Long apiGroupId = apiConfig.getApiGroupId();
            if(groupMap.containsKey(apiGroupId)){
                groupMap.get(apiGroupId).add(apiConfig);
            }else{
                ArrayList<ApiConfig> apiConfigs = new ArrayList<>();
                apiConfigs.add(apiConfig);
                groupMap.put(apiGroupId,apiConfigs);
            }
        }
        ArrayList<ApiGroup> apiGroups = new ArrayList<>();

        for (ApiGroup apiGroup : apiGroupList) {
            Long groupId = apiGroup.getId();
            if(groupMap.containsKey(groupId)){

            }
        }
        result.put(Constants.DATA_LIST, apiGroups);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);

        return result;
    }


    @Override
    public Result<Object> updateApiGroup(long id, User loginUser, ApiGroupParamDto apiGroupParam) {
        //ApiGroupUtil.checkApiGroupParam(apiGroupParam);
        Result<Object> result = new Result<>();
        ApiGroup apiGroup = getById(id);
        if (apiGroup == null) {
            // putMsg(result, Status.RESOURCE_NOT_EXIST);
            return result;
        }

        if (!ApiServiceUtil.hasPerm(loginUser, apiGroup.getCreateUser())) {
            ApiServiceUtil.putMsg(result, Status.USER_NO_OPERATION_PERM);
            return result;
        }

        //check name can use or not
        if (!apiGroup.getName().trim().equals(apiGroup.getName()) && checkName(apiGroup.getName())) {
            //putMsg(result, Status.DATASOURCE_EXIST);
            return result;
        }

        BeanUtil.copyProperties(apiGroupParam, apiGroup, CopyOptions.create().setIgnoreNullValue(true));
        try {
            apiGroup.setUpdateTime(new Date());
            apiGroup.setUpdateUser(loginUser.getUserName());
            apiGroupMapper.updateById(apiGroup);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (DuplicateKeyException ex) {
            logger.error("Update apiGroup error." , ex);
            ApiServiceUtil.putMsg(result, Status.DATASOURCE_EXIST);
        }
        return result;
    }

    private boolean checkName(String name) {
        LambdaQueryWrapper<ApiGroup> lambdaQuery = new LambdaQueryWrapper<ApiGroup>();
        lambdaQuery.eq(ApiGroup::getName, name);
        List<ApiGroup> apiGroupList = apiGroupMapper.selectList(lambdaQuery);
        return apiGroupList != null && !apiGroupList.isEmpty();
    }

    @Override
    public Result<Object> createApiGroup(User loginUser, ApiGroupParamDto apiGroupParam) {
        //DatasourceUtil.checkApiGroupParam(apiGroupParam);
        Result<Object> result = new Result<>();
        // check name can use or not
      /* if (checkName(apiGroupParam.getName())) {
            putMsg(result, Status.DATA_API_GROUP_ERROR);
            return result;
        }*/

        // build apiGroup
        ApiGroup apiGroup = new ApiGroup();
        Date now = new Date();


        //apiGroup.setCreateUser(loginUser.getUserName());
        BeanUtil.copyProperties(apiGroupParam, apiGroup, CopyOptions.create().setIgnoreNullValue(true));

        //apiGroup.setCreateTime(now);
        apiGroup.setUpdateTime(now);
        try {
            apiGroupMapper.insert(apiGroup);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (DuplicateKeyException ex) {
            logger.error("Create apiGroup error." , ex);
            ApiServiceUtil.putMsg(result, Status.DATA_API_GROUP_ERROR);
        }

        return result;
    }

}
